package com.question.business.dept.service.impl;

import com.alibaba.excel.EasyExcelFactory;
import com.alibaba.excel.ExcelWriter;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.question.business.dept.entity.Dept;
import com.question.business.dept.mapper.DeptMapper;
import com.question.business.dept.model.ao.*;
import com.question.business.dept.model.vo.*;
import com.question.business.dept.service.IDeptPostService;
import com.question.business.dept.service.IDeptService;
import com.question.business.org.service.IOrgDeptService;
import com.question.business.user.service.IUserDeptService;
import com.question.common.constants.NumberConstants;
import com.question.common.constants.StringConstants;
import com.question.common.exception.BusinessException;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.ServletOutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * 部门服务实现类
 *
 * @author star
 * @since 2023-09-14
 */
@Slf4j
@Service
@AllArgsConstructor
public class DeptServiceImpl extends ServiceImpl<DeptMapper, Dept> implements IDeptService {

    private final IOrgDeptService orgDeptService;

    private final IDeptPostService deptPostService;

    private final IUserDeptService userDeptService;

    /**
     * 部门分页查询
     *
     * @param ao 请求参数
     * @return Page<DeptVO> 响应参数
     */
    @Override
    public Page<DeptVO> queryDeptPage(DeptPageAO ao) {
        return baseMapper.queryDeptPage(ao.createPage(), ao);
    }

    /**
     * 部门明细查询
     *
     * @param id 部门ID
     * @return DeptDetailVO 响应参数
     */
    @Override
    public DeptDetailVO queryDeptDetail(String id) {
        Dept entity = super.getById(id);
        if (Objects.nonNull(entity)) {
            DeptDetailVO vo = new DeptDetailVO();
            BeanUtils.copyProperties(entity, vo);
            if (StringConstants.PARENT_ID.equals(vo.getParentId())) {
                vo.setParentId(null);
            } else {
                Dept dept = baseMapper.selectById(vo.getParentId());
                vo.setParentName(Objects.nonNull(dept) ? dept.getDeptName() : null);
            }
            vo.setOrgIds(orgDeptService.queryOrgByDeptId(vo.getId()));
            vo.setPostIds(deptPostService.queryPostByDeptId(vo.getId()));
            vo.setUserIds(userDeptService.queryUserByDeptId(vo.getId()));
            return vo;
        }
        return null;
    }

    /**
     * 部门新增数据
     *
     * @param ao 请求参数
     * @return DeptAddVO 响应参数
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public DeptAddVO addDept(DeptAddAO ao) {
        Dept entity = new Dept();
        BeanUtils.copyProperties(ao, entity);
        if (StringUtils.isBlank(entity.getParentId())) {
            entity.setParentId(StringConstants.PARENT_ID);
        }
        super.save(entity);
        orgDeptService.addDeptOrg(entity.getId(), ao.getOrgIds());
        deptPostService.addDeptPost(entity.getId(), ao.getPostIds());
        userDeptService.addDeptUser(entity.getId(), ao.getUserIds());
        DeptAddVO vo = new DeptAddVO();
        vo.setId(entity.getId());
        return vo;
    }

    /**
     * 部门修改数据
     *
     * @param ao 数据
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateDept(DeptUpdateAO ao) {
        Dept entity = new Dept();
        BeanUtils.copyProperties(ao, entity);
        if (StringUtils.isBlank(entity.getParentId())) {
            entity.setParentId(StringConstants.PARENT_ID);
        } else if (ao.getParentId().equals(entity.getId())) {
            throw new BusinessException("上级部门不能选自己");
        }
        super.updateById(entity);
        orgDeptService.addDeptOrg(entity.getId(), ao.getOrgIds());
        deptPostService.addDeptPost(entity.getId(), ao.getPostIds());
        userDeptService.addDeptUser(entity.getId(), ao.getUserIds());
    }

    /**
     * 部门删除数据
     *
     * @param id 部门ID
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteDept(String id) {
        super.removeById(id);
        orgDeptService.addDeptOrg(id, null);
        deptPostService.addDeptPost(id, null);
        userDeptService.addDeptUser(id, null);
    }

    /**
     * 部门批量删除数据
     *
     * @param ids 部门ID
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteBatchDept(List<String> ids) {
        super.removeBatchByIds(ids);
        for (String id : ids) {
            orgDeptService.addDeptOrg(id, null);
            deptPostService.addDeptPost(id, null);
            userDeptService.addDeptUser(id, null);
        }
    }

    /**
     * 部门导出数据
     *
     * @param ao     请求参数
     * @param stream 输出流
     */
    @Override
    public void exportDept(DeptPageAO ao, ServletOutputStream stream) {
        ao.setSize(-1);
        List<DeptVO> vos = queryDeptPage(ao).getRecords();
        List<DeptExcelVO> list = new ArrayList<>(vos.size());
        for (DeptVO vo : vos) {
            DeptExcelVO excelVo = new DeptExcelVO();
            BeanUtils.copyProperties(vo, excelVo);
            list.add(excelVo);
        }

        ExcelWriter excelWriter = EasyExcelFactory.write(stream).build();
        excelWriter.write(list, EasyExcelFactory.writerSheet(NumberConstants.ZERO).head(DeptExcelVO.class).build());
        excelWriter.finish();
    }

    /**
     * 部门启用、停用
     *
     * @param ao 请求参数
     */
    @Override
    public void enableDept(DeptEnabledAO ao) {
        this.lambdaUpdate().eq(Dept::getId, ao.getId()).set(Dept::getEnabled, ao.getEnabled()).update(new Dept());
    }

    /**
     * 部门下拉列表查询
     *
     * @param ao 请求参数
     * @return List<DeptDropDownVO> 响应参数
     */
    @Override
    public List<DeptDropDownVO> queryDeptDropDown(DeptDropDownAO ao) {
        return baseMapper.queryDeptDropDown(ao);
    }
}